<html>

<head>
  <script src="./konva.min.js"></script>
  <meta charset="utf-8" />
  <title>Konva Image Demo</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #f0f0f0;
    }
  </style>
</head>

<body>

  <div id="container"></div>
  <script>
    var width = window.innerWidth;
    var height = window.innerHeight;
    var stage = new Konva.Stage({
      container: 'container',
      width: width,
      height: height,
    });
    var layer = new Konva.Layer();


    var rect = new Konva.Rect({
      x: 20,
      y: 20,
      width: 100,
      height: 100,
      fill: '#cfcfcf',
      stroke: 'black',
      strokeWidth: 1,
      draggable: true,
    });


    var rect1 = new Konva.Rect({
      x: 160,
      y: 190,
      width: 100,
      height: 100,
      fill: '#cfcfcf',
      stroke: 'black',
      strokeWidth: 1,
      draggable: true,
    });

    var arrow = new Konva.Arrow({
      id: 'line',
      x: 10,
      y: 10,
      points: [0, 0, 20, 300],
      pointerLength: 10,
      pointerWidth: 10,
      fill: 'black',
      stroke: 'black',
      strokeWidth: 2,
    });


    layer.add(rect);
    layer.add(rect1);
    layer.add(arrow);

    rect.on('dragmove', () => {
      // rect.position()
      const fromx = rect.x()
      const fromy = rect.y()
      const tox = rect1.x()
      const toy = rect1.y()
      var line = layer.findOne('#line');
      const points = [fromx, fromy, tox, toy]
      line.points(points);
    })


    rect1.on('dragmove', () => {
      // rect.position()
      const fromx = rect.x()
      const fromy = rect.y()
      const tox = rect1.x()
      const toy = rect1.y()
      var line = layer.findOne('#line');
      const points = [fromx, fromy, tox, toy]
      line.points(points);
    })

    // #region 生成目标函数-------------------------
    function generateTargets() {
      var number = 10;
      var result = [];
      while (result.length < number) {
        result.push({
          id: 'target-' + result.length,
          x: stage.width() * Math.random(),
          y: stage.height() * Math.random(),
        });
      }
      return result;
    }
    // #endregion
    function generateConnectors() {
      var number = 10;
      var result = [];
      while (result.length < number) {
        var from = 'target-' + Math.floor(Math.random() * targets.length);
        var to = 'target-' + Math.floor(Math.random() * targets.length);
        if (from === to) {
          continue;
        }
        result.push({
          id: 'connector-' + result.length,
          from: from,
          to: to,
        });
      }
      return result;
    }
    var targets = generateTargets();
    var connectors = generateConnectors();


    targets.forEach((target) => {
      // 创建目标元素
      let rect = new Konva.Rect({
        id: target.id,
        x: target.x,
        y: target.y,
        width: 50,
        height: 50,
        fill: "#cfcfcf",
        draggable: true,
      })
      rect.on('dragmove', () => {
        target.x = rect.x();
        target.y = rect.y();
        updateObjects();
      });
      layer.add(rect)
    })

    // 创建箭头
    connectors.forEach((connect) => {
      var line = new Konva.Arrow({
        stroke: 'black',
        id: connect.id,
        fill: 'black',
      });
 
      layer.add(line);
    });
    function getConnectorPoints(from, to) {
      const dx = to.x - from.x;
        const dy = to.y - from.y;
        let angle = Math.atan2(-dy, dx);

        const radius = 25;

        return [
          from.x + -radius * Math.cos(angle + Math.PI),
          from.y + radius * Math.sin(angle + Math.PI),
          to.x + -radius * Math.cos(angle),
          to.y + radius * Math.sin(angle),
        ];
    }

      function updateObjects() {
        targets.forEach((target) => {
          var node = layer.findOne('#' + target.id);
          node.x(target.x);
          node.y(target.y);
        });

        connectors.forEach((connect) => {
          var line = layer.findOne('#' + connect.id);
          var fromNode = layer.findOne('#' + connect.from);
          var toNode = layer.findOne('#' + connect.to);
          const points = getConnectorPoints(fromNode.position(),toNode.position())
          line.points(points);
        });
      }

    stage.add(layer);
    updateObjects()

  </script>
</body>

</html>